
using System;
using System.Collections.Generic;
using System.Reflection;

namespace Serpis
{
	public class Controller
	{
		private struct ViewModelPropertyPair
		{
			//**	Creamos un struct privado con pares formados por el campo de la vista y la propiedad del modelo
			public ViewModelPropertyPair(PropertyInfo viewPropertyInfo, PropertyInfo modelPropertyInfo)
			{
				ViewPropertyInfo = viewPropertyInfo;
				ModelPropertyInfo = modelPropertyInfo;
			}
			
			public PropertyInfo ViewPropertyInfo;
			public PropertyInfo ModelPropertyInfo;
		}
		
		//**	Creamos una lista de la estructura creada
		private List<ViewModelPropertyPair> viewModelProperties = new List<ViewModelPropertyPair>();
		
		private PluginAttribute[] plugins;
		
		private object model;
		private object view;
		private Validator validator;
		
		public Controller (object model, object view)
		{
			this.model = model;
			this.view = view;
			
			Type modelType = model.GetType();
			Type viewType = view.GetType();
			
			//**	Recorremos las propiedades de la vista.
			foreach (PropertyInfo viewPropertyInfo in viewType.GetProperties())
			{
				//**	Si las propiedades estan decoradas con ModelPropertyAttribute...
				if (viewPropertyInfo.IsDefined(typeof(ModelPropertyAttribute), true)) 
				{
					//Console.WriteLine(viewPropertyInfo.Name);
					PropertyInfo modelPropertyInfo = modelType.GetProperty(viewPropertyInfo.Name);
					viewModelProperties.Add(new ViewModelPropertyPair(viewPropertyInfo, modelPropertyInfo));
				}
			}
			
			validator = new Validator(model);
			
			plugins = (PluginAttribute[])viewType.GetCustomAttributes(typeof(PluginAttribute), true);
			foreach (PluginAttribute plugin in plugins)
				plugin.Controller = this;
			
		}
		
		/// <summary>
		/// Visualiza el modelo en la vista
		/// </summary>
		public void Refresh()
		{
			validator.Validate();
			
			foreach (PluginAttribute plugin in plugins)
				plugin.Refresh();
			
			foreach (ViewModelPropertyPair item in viewModelProperties) {
				object value = item.ModelPropertyInfo.GetValue(model, null);
				item.ViewPropertyInfo.SetValue(view, value, null);
			}
		}
		
		public void Update()
		{
			foreach (ViewModelPropertyPair item in viewModelProperties)
			{
				object value = item.ViewPropertyInfo.GetValue(view, null);
				item.ModelPropertyInfo.SetValue(model, value, null);
			}
		}
		
		public object View {
			get {return view;}
		}
		
		public Validator Validator {
			get {return validator;}
		}
	}
}
